﻿using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.IO;

public class SaveSceneLightmap
{
    [MenuItem("iSane/Utils/Save Scene Lightmap")]
    public static void SaveLightmapOverride()
    {
        string sceneName = EditorSceneManager.GetActiveScene().name;
        string rootPath = "Assets/SceneLightmap";
        string fullPath = rootPath + "/" + sceneName;

        CreateAssetPath(rootPath, fullPath, sceneName);

        CreateAsset(fullPath, sceneName);
    }

    private static void CreateAsset(string fullPath, string sceneName)
    {
        string assetName = string.Format("{0}/{1}.asset", fullPath, sceneName);
        SceneLightmapInfo sli = null;
        if (!File.Exists(assetName))
        {
            sli = ScriptableObject.CreateInstance<SceneLightmapInfo>();
            AssetDatabase.CreateAsset(sli, assetName);
        }
        else
        {
            sli = AssetDatabase.LoadAssetAtPath<SceneLightmapInfo>(assetName);
        }

        SaveTexture(sli, fullPath);
        SaveRenderers(sli);

        EditorUtility.SetDirty(sli);
        AssetDatabase.SaveAssets();
    }

    private static void SaveRenderers(SceneLightmapInfo sli)
    {
        Renderer[] renderers = GameObject.FindObjectsOfType<Renderer>();
        int length = renderers.Length;
        if (0 == length)
        {
            return;
        }

        sli.lightmapInfos = new LightmapInfo[length];
        for(int i=0;i<length;i++)
        {
            sli.lightmapInfos[i] = new LightmapInfo();

            sli.lightmapInfos[i].gameObjectPath = GameObjectNameUtil.GetGameObjectFullPath(renderers[i].gameObject);
            sli.lightmapInfos[i].lightmapIndex = renderers[i].lightmapIndex;
            sli.lightmapInfos[i].lightmapScaleOffset = renderers[i].lightmapScaleOffset;
        }
    }

    private static void SaveTexture(SceneLightmapInfo sli, string fullPath)
    {
        string fileNameColor = "", fileNameDir = "";
        byte[] bytes;
        Texture2D texture = null;
        bool refreshColor, refreshDir;

        int length = LightmapSettings.lightmaps.Length;

        sli.lightmapColorTextures = new Texture2D[length];
        sli.lightmapDirTextures = new Texture2D[length];

        for (int i = 0; i < length; i++)
        {
            refreshColor = false;
            refreshDir = false;

            fileNameColor = string.Format("{0}/{1}.png", fullPath, LightmapSettings.lightmaps[i].lightmapColor.name);
            if (!File.Exists(fileNameColor))
            {
                texture = CopyTexute(LightmapSettings.lightmaps[i].lightmapColor);
                bytes = texture.EncodeToPNG();
                if (null != bytes)
                {
                    File.WriteAllBytes(fileNameColor, bytes);
                }

                refreshColor = true;
            }

            fileNameDir = string.Format("{0}/{1}.png", fullPath, LightmapSettings.lightmaps[i].lightmapDir.name);
            if (!File.Exists(fileNameDir))
            {
                texture = CopyTexute(LightmapSettings.lightmaps[i].lightmapDir);
                bytes = texture.EncodeToPNG();
                if (null != bytes)
                {
                    File.WriteAllBytes(fileNameDir, bytes);
                }

                refreshDir = true;
            }

            if (refreshColor || refreshDir)
            {
                AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
            }

            sli.lightmapColorTextures[i] = AssetDatabase.LoadAssetAtPath<Texture2D>(fileNameColor);
            sli.lightmapDirTextures[i] = AssetDatabase.LoadAssetAtPath<Texture2D>(fileNameDir);
        }
    }

    static void CreateAssetPath(string rootPath, string fullPath, string sceneName)
    {
        if (!AssetDatabase.IsValidFolder(rootPath))
        {
            AssetDatabase.CreateFolder("Assets", "SceneLightmap");
        }

        if (!AssetDatabase.IsValidFolder(fullPath))
        {
            AssetDatabase.CreateFolder("Assets/SceneLightmap", sceneName);
        }
    }

    static Texture2D CopyTexute(Texture2D source)
    {
        int width = source.width;
        int height = source.height;

        Texture2D dest = new Texture2D(width, height, source.format, true);
        Debug.Log(source.format);

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                dest.SetPixel(x, y, source.GetPixel(x, y));
            }
        }

        return dest;
    }
}
